/**********************************************
 *
 * Generate the x86 instructions.
 *
 *********************************************/
#ifndef X86_H
#define X86_H

#include "crossbit/common.h"
#include <cassert>
#include <iostream>
#include <string>
#include <stdlib.h>

namespace crossbit {

    class X86 {
        public:

            /* Encoding of Conditional Test (tttn) Field */
            static const XTUint8 EQ = 0x4;	    /* 0100 */
            static const XTUint8 NE = 0x5;	    /* 0101 */
            static const XTUint8 NA = 0x6;	    /* 0110 */
            static const XTUint8 GT = 0xf;	    /* 1111 */
            static const XTUint8 GE = 0xd;	    /* 1101 */
            static const XTUint8 LT = 0xc;	    /* 1100 */ 
            static const XTUint8 LE = 0xe;	    /* 1110 */
            static const XTUint8 AB = 0x7;	    /* 0111 */
            static const XTUint8 BE = 0x2;	    /* 0010 */

            static const XTUint8 CCENCODINGS[9];
            static const XTUint8 ANTICCENCODINGS[8];

            /* Encoding of General-purpose register field */
            static const XTRegNum EAX = 0;
            static const XTRegNum ECX = 1;
            static const XTRegNum EDX = 2;
            static const XTRegNum EBX = 3;
            static const XTRegNum ESP = 4;
            static const XTRegNum EBP = 5;
            static const XTRegNum ESI = 6;
            static const XTRegNum EDI = 7;

            // mapping regnum to the name
            static const std::string REG2STR[8];

            static  void setP(XTMemAddr p)
            {
                cur_p = p;
            }

            static  XTMemAddr getP()
            {
                return cur_p;
            }

            static void putWord(XTInt32 word)
            {
                *((XTInt32 *)cur_p) = word;
                cur_p += 4;
            }

            //added by zhengjuyu
            static  void nop()
            {
                *((XTUint8*)cur_p++) = 0x90;
            }

            // 01 /r	ADD r/m32, r32	    Add r32 to r/m32
            /* 0000 000w : 11 reg1 reg2 */
            static  void addwImmToReg(XTInt32 imm, XTRegNum reg2)
            {   
                *((XTUint8*)cur_p++) = 0x81;
                *((XTUint8*)cur_p++) = 0xc0 | reg2;
                putWord( imm );

            }
            // 01 /r	ADD r/m32, r32	    Add r32 to r/m32
            /* 0000 000w : 11 reg1 reg2 */
            static  void addRegToReg(XTRegNum reg1, XTRegNum reg2)
            {   
                *((XTUint8*)cur_p++) = 0x01;
                *((XTUint8*)cur_p++) = 0xc0 | (reg1 << 3) | reg2;
            }
            /* inc reg*/
            static  void inc( XTRegNum reg ){
                *((XTUint8*)cur_p++) = 0x40 | reg ;
            }
            /* dec reg*/
            static  void dec( XTRegNum reg ){
                *((XTUint8*)cur_p++) = 0x48 | reg ;
            }
            /* dec wMem*/
            static  void decwMem( XTMemAddr addr ) {
                *((XTUint8*)cur_p++) = 0xff ;
                *((XTUint8*)cur_p++) = 0x0d  ;
                putWord(addr);
            }


            /* 0000 000w : mod reg r/m : disp32*/
            static  void addRegToMem(XTRegNum reg, XTMemAddr mem)
            {
                *((XTUint8*)cur_p++) = 0x01;
                *((XTUint8*)cur_p++) = (reg << 3) | 0x05; /* mod:00 reg r/m:101 */
                putWord(mem);
            }

            /* 1000 00sw : 11 000 reg : immediate data  */
            static  void addImmToReg(XTInt32 imm, XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0x81;
                *((XTUint8*)cur_p++) = 0xc0 | reg;
                putWord(imm);
            }

            /* 0010 000w : 11 reg1 reg2 */
            static  void andRegToReg(XTRegNum reg1, XTRegNum reg2)
            {
                *((XTUint8*)cur_p++) = 0x21;
                *((XTUint8*)cur_p++) = 0xc0 | (reg1 << 3) | reg2;
            }

            /* 1000 00sw : 11 100 reg : immediate data */
            static  void andImmToReg(XTInt32 imm, XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0x81;
                *((XTUint8*)cur_p++) = 0xe0 | reg;
                putWord(imm);
            }

            /* 0011 000w : 11 reg1 reg2 */
            static  void xorRegToReg(XTRegNum reg1, XTRegNum reg2)
            {
                *((XTUint8*)cur_p++) = 0x31;
                *((XTUint8*)cur_p++) = 0xc0 | (reg1 << 3) | reg2;
            }

            /* 1000 00sw : 11 110 reg : immediate data */
            static  void xorImmToReg(XTInt32 imm, XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0x81;
                *((XTUint8*)cur_p++) = 0xf0 | reg;
                putWord(imm);
            }

            /* 0000 100w : 11 reg1 reg2 */
            static  void orRegToReg(XTRegNum reg1, XTRegNum reg2)
            {
                *((XTUint8*)cur_p++) = 0x09;
                *((XTUint8*)cur_p++) = 0xc0 | (reg1 << 3) | reg2;
            }

            /* 1000 00sw : 11 001 reg : immediate data */
            static  void orImmToReg(XTInt32 imm, XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0x81;
                *((XTUint8*)cur_p++) = 0xc8 | reg;
                putWord(imm);
            }

            /* 0010 100w : 11 reg1 reg2 */
            static  void subRegFromReg(XTRegNum reg1, XTRegNum reg2)
            {
                *((XTUint8*)cur_p++) = 0x29;
                *((XTUint8*)cur_p++) = 0xc0 | (reg1 << 3) | reg2;
            }

            /* 1000 000w : 11 101 reg : immediate data */
            static  void subImmFromReg(XTInt32 imm, XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0x81;
                *((XTUint8*)cur_p++) = 0xe8 | reg;
                putWord(imm);
            }

            /* 1000 000w : 11 101 reg : immediate data  */
            static  void subImm8FromReg(XTUint8 imm, XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0x80;
                *((XTUint8*)cur_p++) = 0xe8 | reg;
                *((XTUint8*)cur_p++) = imm;
            }

            /* 1111 011w : 11 010 reg */
            static  void notReg(XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0xf7;
                *((XTUint8*)cur_p++) = 0xd0 | reg;
            }

            /* 1111 011w : 11 011 reg */
            static  void negReg(XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0xf7;
                *((XTUint8*)cur_p++) = 0xd8 | reg;
            }

            /* 1100 000w : 11 100 reg : imm8 data */
            static  void shlRegByImm(XTRegNum reg, XTUint8 imm)
            {
                *((XTUint8*)cur_p++) = 0xc1;
                *((XTUint8*)cur_p++) = 0xe0 | reg;
                *(( XTPStr )cur_p++) = imm;
            }

            /* 1101 001w : 11 100 reg */
            static  void shlRegByCl(XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0xd3;
                *((XTUint8*)cur_p++) = 0xe0 | reg;
            }

            /* 1100 000w : 11 111 reg : imm8 data */
            static  void sarRegByImm(XTRegNum reg, XTUint8 imm)
            {
                *((XTUint8*)cur_p++) = 0xc1;
                *((XTUint8*)cur_p++) = 0xf8 | reg;
                *(( XTPStr )cur_p++) = imm;
            }

            /* 1101 001w : 11 111 reg */
            static  void sarRegByCl(XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0xd3;
                *((XTUint8*)cur_p++) = 0xf8 | reg;
            }

            /* 1100 000w : 11 101 reg : imm8 data */
            static  void shrRegByImm(XTRegNum reg, XTUint8 imm)
            {
                *((XTUint8*)cur_p++) = 0xc1;
                *((XTUint8*)cur_p++) = 0xe8 | reg;
                *(( XTPStr )cur_p++) = imm;
            }

            /* 1101 001w : 11 101 reg */
            static  void shrRegByCl(XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0xd3;
                *((XTUint8*)cur_p++) = 0xe8 | reg;
            }

            /* 1111 011w : 11 101 reg */
            static  void imulEaxToReg(XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0xf7;
                *((XTUint8*)cur_p++) = 0xe8 | reg;
            }

            /* 1111 011w : 11 100 reg */
            static  void mulEaxToReg(XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0xf7;
                *((XTUint8*)cur_p++) = 0xe0 | reg;
            }

            /* 1111 011w : 11 111 reg */
            static  void idivEdxEaxByReg(XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0xf7;
                *((XTUint8*)cur_p++) = 0xf8 | reg;
            }

            /* 111 011w : 11 110 reg */
            static  void divEdxEaxByReg(XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0xf7;
                *((XTUint8*)cur_p++) = 0xf0 | reg;
            }

            /* 1100 011w : 11 000 reg : immediate data */
            static  void movwImmToReg(XTInt32 imm, XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0xc7; /* 1100 011w, w = 1 */
                *((XTUint8*)cur_p++) = 0xc0 | reg;
                putWord(imm);
            }


            static  void movImmToMem(XTInt32 imm, XTMemAddr mem, BlockSize size)
            {
                switch(size)
                {
                    case BYTE: movbImmToMem(imm, mem); break;
                    case HALFWORD: movhImmToMem(imm, mem); break;
                    case WORD: movwImmToMem(imm, mem); break;
                }

            }

            static  void movbImmToMem(XTInt32 imm, XTMemAddr mem)
            {
                *((XTUint8*)cur_p++) = 0xc6;
                *((XTUint8*)cur_p++) = 0x5;
                putWord(mem);
                *((XTUint8*)cur_p++) = (XTInt8)imm;
            }

            static  void movhImmToMem(XTInt32 imm, XTMemAddr mem)
            {
                *((XTUint8*)cur_p++) = 0x66;
                *((XTUint8*)cur_p++) = 0xc7;
                *((XTUint8*)cur_p++) = 0x5;
                putWord(mem);
                *((XTUint16*)(cur_p)) = (XTUint16)imm;
                cur_p += 2;
            }

            /* 1100 011w : mod 000 r/m : immediate data*/
            static  void movwImmToMem(XTInt32 imm, XTMemAddr mem)
            {
                *((XTUint8*)cur_p++) = 0xc7;
                *((XTUint8*)cur_p++) = 0x5; /* mod:00 000 r/m:101 */
                putWord(mem);
                putWord(imm);
            }

            static  void movImmToMem(XTInt32 imm, XTRegNum reg, XTInt32 disp, BlockSize size)
            {
                switch(size)
                {
                    case WORD: movwImmToMem(imm, reg, disp);break;
                    case HALFWORD: movhImmToMem(imm, reg, disp);break;
                    case BYTE: movbImmToMem(imm, reg, disp);break;
                }
            }

            static  void movbImmToMem(XTInt32 imm, XTRegNum reg, XTInt32 disp)
            {
                *((XTUint8*)cur_p++) = 0xc6;
                *((XTUint8*)cur_p++) = 0x80 | reg;
                putWord(disp);
                *((XTUint8*)cur_p++) = (XTInt8)imm;
            }

            static  void movhImmToMem(XTInt32 imm, XTRegNum reg, XTInt32 disp)
            {
                *((XTUint8*)cur_p++) = 0x66;
                *((XTUint8*)cur_p++) = 0xc7;
                *((XTUint8*)cur_p++) = 0x80 | reg;
                putWord(disp);
                *((XTUint16*)(cur_p)) = (XTUint16)imm;
                cur_p += 2;
            }

            /* 1100 011w : mod 000 r/m : immediate data*/
            static  void movwImmToMem(XTInt32 imm, XTRegNum reg, XTInt32 disp)
            {
                *((XTUint8*)cur_p++) = 0xc7;
                *((XTUint8*)cur_p++) = 0x80 | reg; /* mod:10 000 r/m:reg */
                putWord(disp);
                putWord(imm);
            }

            static  void movMemToReg(XTMemAddr mem, BlockSize size, XTRegNum dst)
            {
                switch (size) {
                    case WORD:	    movwMemToReg(mem, dst); break;
                    case HALFWORD:  movhMemToReg(mem, dst); break;
                    case BYTE:	    movbMemToReg(mem, dst); break;
                }
            }

            /* 1000 1011 : mod reg r/m  */
            static  void movwMemToReg(XTMemAddr mem, XTRegNum dst)
            {
                *((XTUint8*)cur_p++) = 0x8b;    /* 1000 1011 */
                *((XTUint8*)cur_p++) = dst << 3 | 0x5;  /* mod:00, reg, r/m:101 */
                putWord(mem);
            }

            /* 1000 1010 : mod reg r/m  */
            static  void movbMemToReg(XTMemAddr mem, XTRegNum dst)
            {
                *((XTUint8*)cur_p++) = 0x8a;    /* 1000 1011 */
                *((XTUint8*)cur_p++) = dst << 3 | 0x5;  /* mod:00, reg, r/m:101 */
                *((XTUint32*)cur_p) = (XTUint32)mem;	/* discur_p32 */
                cur_p += 4;
            }

            /* prefix:0x66 1000 1011 : mod reg r/m  */
            static  void movhMemToReg(XTMemAddr mem, XTRegNum dst)
            {
                *((XTUint8*)cur_p++) = 0x66;
                *((XTUint8*)cur_p++) = 0x8b;    /* 1000 1011 */
                *((XTUint8*)cur_p++) = dst << 3 | 0x5;  /* mod:00, reg, r/m:101 */
                *((XTUint32*)cur_p) = (XTUint32)mem;	/* discur_p32 */
                cur_p += 4;
            }

            static  void movMemToReg(XTRegNum reg, XTInt32 disp, BlockSize size, XTRegNum dst)
            {
                if( reg != ESP && reg != EBP && disp  == 0 ) {
                    movMemToReg( reg , size , dst );
                } else {
                    switch (size) {
                        case WORD:		movwMemToReg(reg, disp, dst); break;
                        case HALFWORD:	movhMemToReg(reg, disp, dst); break;
                        case BYTE:		movbMemToReg(reg, disp, dst); break;
                    }
                }
            }

            /* 1000 1011 : mod reg r/m  */
            static  void movwMemToReg(XTRegNum reg, XTInt32 disp, XTRegNum dst)
            {
                assert(reg != ESP);
                if( disp == 0 && reg != EBP ) {
                    movwMemToReg( reg , dst );
                } else {
                    *((XTUint8*)cur_p++) = 0x8b;
                    *((XTUint8*)cur_p++) = 0x80 | (dst << 3) | reg;    /* mod:10, dst, r/m:reg */
                    *((XTInt32 *)cur_p) =  disp;
                    cur_p += 4;
                }
            }

            /* 1000 1010 : mod reg r/m  */
            static  void movbMemToReg(XTRegNum reg, XTInt32 disp, XTRegNum dst)
            {
                assert(reg != ESP);
                if( disp == 0 && reg != EBP ) {
                    movbMemToReg( reg , dst );
                } else {
                    *((XTUint8*)cur_p++) = 0x8a;
                    *((XTUint8*)cur_p++) = 0x80 | (dst << 3) | reg;    /* mod:10, dst, r/m:reg */
                    *((XTInt32 *)cur_p) =  disp;
                    cur_p += 4;
                }
            }

            /* prefix:0x66 1000 1011 : mod reg r/m  */
            static  void movhMemToReg(XTRegNum reg, XTInt32 disp, XTRegNum dst)
            {
                assert(reg != ESP);
                if( disp == 0 && reg != EBP ) {
                    movhMemToReg( reg , dst );
                } else {
                    *((XTUint8*)cur_p++) = 0x66;
                    *((XTUint8*)cur_p++) = 0x8b;
                    *((XTUint8*)cur_p++) = 0x80 | (dst << 3) | reg;    /* mod:10, dst, r/m:reg */
                    *((XTInt32 *)cur_p) =  disp;
                    cur_p += 4;
                }
            }


            static  void movMemToReg(XTRegNum src, BlockSize size, XTRegNum dst)
            {
                switch (size) {
                    case WORD:		movwMemToReg(src, dst); break;
                    case HALFWORD:	movhMemToReg(src, dst); break;
                    case BYTE:		movbMemToReg(src, dst); break;
                }
            }

            /* 1000 1011 : mod dst r/m */
            static  void movwMemToReg(XTRegNum src, XTRegNum dst)
            {
                assert(src != ESP && src != EBP);
                *((XTUint8*)cur_p++) = 0x8b;
                *((XTUint8*)cur_p++) = (dst << 3) | src; /* mod:00 dst r/m:src */
            }

            /* 1000 1010 : mod dst r/m */
            static  void movbMemToReg(XTRegNum src, XTRegNum dst)
            {
                assert(src != ESP && src != EBP);
                *((XTUint8*)cur_p++) = 0x8a;
                *((XTUint8*)cur_p++) = (dst << 3) | src; /* mod:00 dst r/m:src */
            }

            /* prefix:0x66 1000 1011 : mod dst r/m */
            static  void movhMemToReg(XTRegNum src, XTRegNum dst)
            {
                assert(src != ESP && src != EBP);
                *((XTUint8*)cur_p++) = 0x66;
                *((XTUint8*)cur_p++) = 0x8b;
                *((XTUint8*)cur_p++) = (dst << 3) | src; /* mod:00 dst r/m:src */
            }

            static  void movRegToMem(XTRegNum reg, BlockSize size, XTMemAddr addr)
            {
                switch (size) {
                    case WORD:		movwRegToMem(reg, addr); break;
                    case HALFWORD:	movhRegToMem(reg, addr); break;
                    case BYTE:		movbRegToMem(reg, addr); break;
                }
            }

            /* 1000 1001 : mod reg r/m */
            static  void movwRegToMem(XTRegNum reg, XTMemAddr addr)
            {
                *((XTUint8*)cur_p++) = 0x89;    /* 1000 1001 */
                *((XTUint8*)cur_p++) = reg << 3 | 0x5;  /* mod:00, reg, r/m:101 */
                *((XTUint32*)cur_p) = (XTUint32)addr;	/* discur_p32 */
                cur_p += 4;
            }

            /* 1000 1000 : mod reg r/m */
            static  void movbRegToMem(XTRegNum reg, XTMemAddr addr)
            {
                *((XTUint8*)cur_p++) = 0x88;    /* 1000 1001 */
                *((XTUint8*)cur_p++) = reg << 3 | 0x5;  /* mod:00, reg, r/m:101 */
                *((XTUint32*)cur_p) = (XTUint32)addr;	/* discur_p32 */
                cur_p += 4;
            }

            /* prefix:0x66 1000 1001 : mod reg r/m */
            static  void movhRegToMem(XTRegNum reg, XTMemAddr addr)
            {
                *((XTUint8*)cur_p++) = 0x66;
                *((XTUint8*)cur_p++) = 0x89;    /* 1000 1001 */
                *((XTUint8*)cur_p++) = reg << 3 | 0x5;  /* mod:00, reg, r/m:101 */
                *((XTUint32*)cur_p) = (XTUint32)addr;	/* discur_p32 */
                cur_p += 4;
            }

            static void movRegToMem(XTRegNum src, BlockSize size, XTRegNum reg, XTInt32 disp)
            {


                if( reg != ESP && reg != EBP && disp == 0 ) {
                    movRegToMem( src ,(BlockSize)size, (XTRegNum)reg );
                } else {
                    switch (size) {
                        case WORD:		movwRegToMem(src, reg, disp); break;
                        case HALFWORD:	movhRegToMem(src, reg, disp); break;
                        case BYTE:		movbRegToMem(src, reg, disp); break;
                    }
                }
            }

            /* 1000 1001 : mod reg r/m */
            static  void movwRegToMem(XTRegNum src, XTRegNum reg, XTInt32 disp)
            {
                assert(reg != ESP);
                if( reg != EBP && disp == 0 ) {
                    movwRegToMem( src , reg );
                } else {
                    *((XTUint8*)cur_p++) = 0x89;
                    *((XTUint8*)cur_p++) = 0x80 | (src << 3) | reg;
                    *((XTInt32 *)cur_p) = disp;
                    cur_p += 4;
                }
            }

            /* 1000 1000 : mod reg r/m */
            static  void movbRegToMem(XTRegNum src, XTRegNum reg, XTInt32 disp)
            {
                assert(reg != ESP);
                if( reg != EBP && disp == 0 ) {
                    movbRegToMem( src , reg );
                } else {
                    *((XTUint8*)cur_p++) = 0x88;
                    *((XTUint8*)cur_p++) = 0x80 | (src << 3) | reg;
                    *((XTInt32 *)cur_p) = disp;
                    cur_p += 4;
                }
            }

            /* 1000 1001 : mod reg r/m */
            static  void movhRegToMem(XTRegNum src, XTRegNum reg, XTInt32 disp)
            {
                assert(reg != ESP);

                if( reg != EBP && disp == 0 ) {
                    movhRegToMem( src , reg );
                } else {

                    *((XTUint8*)cur_p++) = 0x66;
                    *((XTUint8*)cur_p++) = 0x89;
                    *((XTUint8*)cur_p++) = 0x80 | (src << 3) | reg;
                    *((XTInt32 *)cur_p) = disp;
                    cur_p += 4;
                }
            }



            static  void movRegToMem(XTRegNum src, BlockSize size, XTRegNum dst)
            {
                switch (size) {
                    case WORD:		movwRegToMem(src, dst);
                                    break;
                    case HALFWORD:	movhRegToMem(src, dst);
                                    break;
                    case BYTE:		movbRegToMem(src, dst);
                                    break;
                }
            }

            /* 1000 1001 : mod src r/m */
            static  void movwRegToMem(XTRegNum src, XTRegNum dst)
            {
                assert(dst != ESP && dst != EBP);
                *((XTUint8*)cur_p++) = 0x89;
                *((XTUint8*)cur_p++) = (src << 3) | dst;
            }

            /* 1000 1000 : mod src r/m */
            static  void movbRegToMem(XTRegNum src, XTRegNum dst)
            {
                assert(dst != ESP && dst != EBP);
                *((XTUint8*)cur_p++) = 0x88;
                *((XTUint8*)cur_p++) = (src << 3) | dst;
            }

            /* prefix:0x66 1000 1001 : mod src r/m */
            static  void movhRegToMem(XTRegNum src, XTRegNum dst)
            {
                assert(dst != ESP && dst != EBP);
                *((XTUint8*)cur_p++) = 0x66;
                *((XTUint8*)cur_p++) = 0x89;
                *((XTUint8*)cur_p++) = (src << 3) | dst;
            }

            /* 1000 101w : 11 dst src */
            static  void movwRegToReg(XTRegNum reg1, XTRegNum reg2)
            {
                *((XTUint8*)cur_p++) = 0x8b;   /* 1000 1011 */ 
                *((XTUint8*)cur_p++) = 0xc0 | (reg2 << 3) | reg1;	/* 11 reg1 reg2 */
            }

            static  void movbRegToReg(XTRegNum reg1, XTRegNum reg2)
            {
                *((XTUint8*)cur_p++) = 0x8a;
                *((XTUint8*)cur_p++) = 0xc0 | ( reg2 << 3) | reg1;
            }

            /* 0000 1111 : 1011 1110 : 11 dst src */
            static  void movsblRegToReg(XTRegNum src, XTRegNum dst)
            {
                *((XTUint8*)cur_p++) = 0x0f;
                *((XTUint8*)cur_p++) = 0xbe;
                *((XTUint8*)cur_p++) = 0xc0 | (dst << 3) | src;
            }

            /* 0000 1111 : 1011 1111 : 11 dst src */
            static  void movswlRegToReg(XTRegNum src, XTRegNum dst)
            {
                *((XTUint8*)cur_p++) = 0x0f;
                *((XTUint8*)cur_p++) = 0xbf;
                *((XTUint8*)cur_p++) = 0xc0 | (dst << 3) | src;
            }

            /* 0000 1111 : 1011 0110 : 11 dst src */
            static  void movzblRegToReg(XTRegNum src, XTRegNum dst)
            {
                *((XTUint8*)cur_p++) = 0x0f;
                *((XTUint8*)cur_p++) = 0xb6;
                *((XTUint8*)cur_p++) = 0xc0 | (dst << 3) | src;
            }

            /* 0000 1111 : 1011 0111 : 11 dst src */
            static  void movzwlRegToReg(XTRegNum src, XTRegNum dst)
            {
                *((XTUint8*)cur_p++) = 0x0f;
                *((XTUint8*)cur_p++) = 0xb7;
                *((XTUint8*)cur_p++) = 0xc0 | (dst << 3) | src;
            }

            /* 1100 0011 */
            static  void ret()
            {
                *((XTUint8*)cur_p++) = 0xc3;
            }

            /* 0011 100w : 11 reg2 reg1 */
            static  void cmpRegWithReg(XTRegNum reg1, XTRegNum reg2)
            {
                *((XTUint8*)cur_p++) = 0x39;
                *((XTUint8*)cur_p++) = 0xc0 | (reg2 << 3) | reg1;
            }


            /* 1000 0001 : 11 111 reg : immediate data */
            static  void cmpImmWithReg(XTInt32 imm, XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0x81;
                *((XTUint8*)cur_p++) = 0xf8 | reg;
                putWord(imm);
            }

            static  void fcmpFpregWithFpregPop()
            {
                *((XTUint8*)cur_p++) = 0xdf;
                *((XTUint8*)cur_p++) = 0xf1;
            }

            /* 1000 0101 : 11 reg1 reg2 */
            static  void testRegWithReg(XTRegNum reg1, XTRegNum reg2)
            {
                *((XTUint8*)cur_p++) = 0x85;
                *((XTUint8*)cur_p++) = 0xc0 | (reg1 << 3) | reg2;
            }

            /* 0000 1111 : 1001 tttn : 11 000 reg */
            static  void setcc(XTRegNum reg, XTUint8 tttn)
            {
                *((XTUint8*)cur_p++) = 0x0f;
                *((XTUint8*)cur_p++) = 0x90 | tttn;
                *((XTUint8*)cur_p++) = 0xc0 | reg;
            }

            /* 1111 1111 : mod 100 r/m */
            static  void jmpAbsoluteIndirectMemory(XTMemAddr addr)
            {
                *((XTUint8*)cur_p++) = 0xff;
                *((XTUint8*)cur_p++) = /* 00 100 101 */ 0x25;
                *((XTUint32*)cur_p) = addr;
                cur_p += 4;
            }

            /* 1111 1111 : 1110 0 reg*/
            static  void jmpAbsoluteIndirectReg(XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0xff;
                *((XTUint8*)cur_p++) = 0xe0 | reg;
            }

            /* 1110 1001 : full displacement */
            static  void jmpRelativeDirectDisp32(XTInt32 disp)
            {
                *((XTUint8*)cur_p++) = 0xe9;
                putWord(disp);
            }

            /* 0000 1111 : 1000 tttn : full displacement */
            static  void jccRelativeDirectDisp32(XTInt32 disp, XTUint8 tttn)
            {
                *((XTUint8*)cur_p++) = 0x0f;
                *((XTUint8*)cur_p++) = 0x80 | tttn;
                putWord(disp);
            }

            /* 0000 1111 : 1000 0100 : full displacement */
            static  void jeRelativeDirectDisp32(XTInt32 disp)
            {
                *((XTUint8*)cur_p++) = 0x0f;
                *((XTUint8*)cur_p++) = 0x84;
                putWord(disp);
            }

            static  void jneRelativeDirectDisp32(XTInt32 disp)
            {
                *((XTUint8*)cur_p++) = 0x0f;
                *((XTUint8*)cur_p++) = 0x85;
                putWord(disp);
            }

            // 1110 1000 : displacement32
            static  void callRelativeDirectDisp32(XTInt32 disp)
            {
                *((XTUint8*)cur_p++) = 0xe8;
                putWord(disp);
            }

            // 0110 1000 : imm32
            static  void pushImm32(XTInt32 imm32)
            {
                *((XTUint8*)cur_p++) = 0x68;
                putWord(imm32);
            }

            // 0x60
            static  void pushAll()
            {
                *((XTUint8*)cur_p++) = 0x60;
            }

            // 0101 0 reg
            static  void pushReg(XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0x50 | reg;
            }

            // 0101 1 reg
            static  void popReg(XTRegNum reg)
            {
                *((XTUint8*)cur_p++) = 0x58 | reg;
            }

            // 0x61
            static  void popAll() 
            {
                *((XTUint8*)cur_p++) = 0x61;
            }

            // float-poXTInt32instruction

            //0xd9	,flds 32bit
            static  void fpPushFreg32(XTMemAddr addr)
            {
                *((XTUint8*)cur_p++) = 0xd9;
                *((XTUint8*)cur_p++) = 0x05;
                *(XTMemAddr *)cur_p = addr;
                cur_p+=4;
            }

            static  void fpPushFreg32BaseDisp(XTRegNum reg, XTInt32 disp)
            {
                *((XTUint8*)cur_p++) = 0xd9;
                *((XTUint8*)cur_p++) = 0x80 | reg;
                putWord(disp);
            }
            //0xdd	,fldl 64bit
            static  void fpPushFreg64(XTMemAddr addr)
            {
                *((XTUint8*)cur_p++) = 0xdd;
                *((XTUint8*)cur_p++) = 0x05;
                *(XTMemAddr *)cur_p = addr;
                cur_p+=4;
            }

            static  void fpPushFreg64BaseDisp(XTRegNum reg, XTInt32 disp)
            {
                *((XTUint8*)cur_p++) = 0xdd;
                *((XTUint8*)cur_p++) = 0x80 | reg;
                putWord(disp);
            }
            //0xdb	,fildl addr
            static  void intPushFreg32(XTMemAddr addr)
            {
                *((XTUint8*)cur_p++) = 0xdb;
                *((XTUint8*)cur_p++) = 0x05;
                *(XTMemAddr *)cur_p = addr;
                cur_p+=4;
            }

            //0xde	,fildll addr
            static  void longlongPushFreg64(XTMemAddr addr)
            {
                *((XTUint8*)cur_p++) = 0xde;
                *((XTUint8*)cur_p++) = 0x2d;
                *(XTMemAddr *)cur_p = addr;
                cur_p+=4;
            }
            //0xd9	,fstps 32bit
            static  void fpPopFreg32(XTMemAddr addr)
            {
                *((XTUint8*)cur_p++) = 0xd9;
                *((XTUint8*)cur_p++) = 0x1d;
                *(XTMemAddr *)cur_p = addr;
                cur_p+=4;
            }

            static  void fpPopFreg32BaseDisp(XTRegNum reg, XTInt32 disp)
            {
                *((XTUint8*)cur_p++) = 0xd9;
                *((XTUint8*)cur_p++) = 0x98 | reg;
                putWord(disp);
            }

            //0xdd	,fstpl 64bit
            static  void fpPopFreg64(XTMemAddr addr)
            {
                *((XTUint8*)cur_p++) = 0xdd;
                *((XTUint8*)cur_p++) = 0x1d;
                *(XTMemAddr *)cur_p = addr;
                cur_p+=4;
            }

            static  void fpPopFreg64BaseDisp(XTRegNum reg, XTInt32 disp)
            {
                *((XTUint8*)cur_p++) = 0xdd;
                *((XTUint8*)cur_p++) = 0x98 | reg;
                putWord(disp);
            }

            //0xdb	,fistpl 32bit   
            static  void intPopFreg32(XTMemAddr addr)
            {
                *((XTUint8*)cur_p++) = 0xdb;
                *((XTUint8*)cur_p++) = 0x1d;
                *(XTMemAddr *)cur_p = addr;
                cur_p+=4;
            }
            //0xdb	,fistpll 64bit
            static  void longlongPopFreg64(XTMemAddr addr)
            {
                *((XTUint8*)cur_p++) = 0xde;
                *((XTUint8*)cur_p++) = 0x3d;
                *(XTMemAddr *)cur_p = addr;
                cur_p+=4;
            }
            //0xde	,FADDP1 32bit
            static  void fpAdd32()
            {
                *((XTUint8*)cur_p++) = 0xde;
                *((XTUint8*)cur_p++) = 0xc1;
            }

            //0xde	,FADDP1 64bit
            static  void fpAdd64()
            {
                *((XTUint8*)cur_p++) = 0xde;
                *((XTUint8*)cur_p++) = 0xc1;
            }

            //0xd8	,FSUBP1 32bit
            //ST(1)<-ST(1)-ST(0)
            //pop ST(0)
            static  void fpSub32()
            {
                *((XTUint8*)cur_p++) = 0xde;
                *((XTUint8*)cur_p++) = 0xe9;
            }

            //0xd8	,FSUBP1 64bit
            //ST(1)<-ST(1)-ST(0)
            //pop ST(0)
            static  void fpSub64()
            {
                *((XTUint8*)cur_p++) = 0xde;
                *((XTUint8*)cur_p++) = 0xe9;
            }
            // 0xde	,FMULTP 32/64
            static  void fpMult32()
            {
                *((XTUint8*)cur_p++) = 0xde;
                *((XTUint8*)cur_p++) = 0xc9;
            }

            // 0xde	,FMULTP 32/64
            static  void fpMult64()
            {
                *((XTUint8*)cur_p++) = 0xde;
                *((XTUint8*)cur_p++) = 0xc9;
            }

            // 0x	,FDIVP  32/64
            static  void fpDiv32()
            {
                *((XTUint8*)cur_p++) = 0xde;
                *((XTUint8*)cur_p++) = 0xf9;
            }

            static  void fpDiv64()
            {
                *((XTUint8*)cur_p++) = 0xde;
                *((XTUint8*)cur_p++) = 0xf9;
            }

            static  void fpChs()
            {
                *((XTUint8*)cur_p++) = 0xd9;
                *((XTUint8*)cur_p++) = 0xe0;
            }

            static  void fpSqrt()
            {
                *((XTUint8*)cur_p++) = 0xd9;
                *((XTUint8*)cur_p++) = 0xfa;
            }

            static  void fabs()
            {
                *((XTUint8*)cur_p++) = 0xd9;
                *((XTUint8*)cur_p++) = 0xe1;
            }
            static  void leaRegToReg( XTRegNum reg , XTUint32 base , BlockSize size , XTRegNum dst ) {
                if( size == HALFWORD ) {
                    *((XTUint8*)cur_p++) = 0x8d;
                    *((XTUint8*)cur_p++) = dst << 3 | 0x4; /* mod : 00 , reg , r/m : 100 */
                    *((XTUint8*)cur_p++) = 0x40 | (reg << 3) | 0x5; /* ss : 01 */
                    *((XTUint32*)cur_p ) = base;
                    cur_p += 4;
                } else if( size == DWORD ) {
                    *((XTUint8*)cur_p++) = 0x8d;
                    *((XTUint8*)cur_p++) = dst << 3 | 0x4; /* mod : 00 , reg , r/m : 100 */
                    *((XTUint8*)cur_p++) = 0xc0 | (reg << 3) | 0x5; /* ss : 11 */
                    *((XTUint32*)cur_p ) = base;
                    cur_p += 4;
                } else {
                    printf("error in X86.h # leaRegToReg\n");
                    exit(1);
                }
            } 

            static  void fldcw( XTMemAddr addr )
            {*((XTUint8*)cur_p++) = 0xdb; *((XTUint8*)cur_p++)=0xe2;
                *((XTUint8*)cur_p++) = 0xd9;
                *((XTUint8*)cur_p++) = 0x2d;
                putWord(addr);
            }

            static  void fstcw( XTMemAddr addr )
            {*((XTUint8*)cur_p++) = 0x9b;
                *((XTUint8*)cur_p++) = 0xd9;
                *((XTUint8*)cur_p++) = 0x3d;
                putWord(addr);
            }

            static  void fincstp()
            {
                *((XTUint8*)cur_p++) = 0xdd;
                *((XTUint8*)cur_p++) = 0xc0;
                *((XTUint8*)cur_p++) = 0xd9;
                *((XTUint8*)cur_p++) = 0xf7;
            }

            //0xcc
            //Added by Zheng Juyu, for single break
            static  void sbreak()
            {
                *((XTUint8*)cur_p++) = 0xcc;
            }
        private:
            static XTMemAddr cur_p;

            //												static struct RegisterFile saved;

    };

}
#endif
